﻿using Common.Extension;
using DesignModeConsole.行为型.解释器模式.告警规则简单;
using DesignModeConsole.行为型.解释器模式.告警规则进阶;
using DesignModeConsole.行为型.解释器模式.自定义1;

namespace DesignModeConsole.行为型.解释器模式;

/// <summary>
/// 解释器模式
/// </summary>
public class InterpreterService : IService
{
    public void Main()
    {
        //// 加减乘除示例
        //SampleOperator("4 5 6 7 + * +");

        // 加减乘除封装示例
        //var interpreter = new ExpressionInterpreter1();
        //interpreter.SampleOperator("4 5 6 7 + * +");

        // 告警
        //AlarmRuleHandler();

        // AlertRuleHandler2();

        // 自定义规则处理3
        CustomRuleHandler3();
    }

    /// <summary>
    /// 实现一个简单的语法算法
    /// 4 5 6 7 - * +
    /// 实现(4-5)*6+7
    /// </summary>
    public void SampleOperator(string str)
    {
        var list = new List<int>();

        var strArray = str.Split(" ");
        for (var i = 0; i < (strArray.Length + 1) / 2; i++)
        {
            list.Add(strArray[i].ToInt());
        }

        var startIndex = (strArray.Length + 1) / 2;
        for (var i = startIndex; i < strArray.Length; i++)
        {
            if (strArray[i] is not "+" and not "-" and not "*" and not "/")
            {
                throw new NotSupportedException("不支持的操作符");
            }

            var number1 = list[0];
            var number2 = list[1];

            list.RemoveAt(0);
            list.RemoveAt(0);

            var result = strArray[i] switch
            {
                "+" => number1 + number2,
                "-" => number1 - number2,
                "*" => number1 * number2,
                "/" => number1 / number2,
                _ => 0
            };
            list.Insert(0, result);
        }

        if (list.Count != 1)
        {
            throw new ArgumentException("无效的表达式");
        }

        Console.WriteLine($"计算结果是  {list[0]}");
    }

    /// <summary>
    /// 告警规则处理
    /// </summary>
    public void AlarmRuleHandler()
    {
        /*
         一般来讲，监控系统支持开发者自定义告警规则，比如我们可以用下面这样一个表达式，来
            表示一个告警规则，它表达的意思是：每分钟 API 总出错数超过 100 或者每分钟 API 总调
            用数超过 10000 就触发告警。

        为了简化讲解和代码实现，我们假设自定义的告警规则只包含“||、&&、>、<、==”这
        五个运算符，其中，“>、<、==”运算符的优先级高于“||、&&”运算符，“&&”运算
        符优先级高于“||”。在表达式中，任意元素之间需要通过空格来分隔。除此之外，用户可
        以自定义要监控的 key，比如前面的 api_error_per_minute、api_count_per_minute。
         */

        // 使用解释器模式去解析下面的规则，然后判断该规则在填充下面数据的情况下返回什么
        const string rule = "key1 > 100 && key2 < 30 || key3 < 100 || key4 = 88";
        const string rule2 = "key1 > 100 && (key2 < 30 || key3 < 100 || key4 = 88)";

        var interpreter = new AlertRuleInterpreter1(rule);
        var stats = new Dictionary<string, long> { { "key1", 101 }, { "key3", 121 }, { "key4", 88 } };
        var alert = interpreter.Interpret(stats);
        Console.WriteLine($"根据告警规则 当前状态为：{(alert ? "警告" : "无警告")}");
    }

    /// <summary>
    /// 告警规则处理-支持括号嵌套
    /// </summary>
    private void AlertRuleHandler2()
    {
        /*
         一般来讲，监控系统支持开发者自定义告警规则，比如我们可以用下面这样一个表达式，来
            表示一个告警规则，它表达的意思是：每分钟 API 总出错数超过 100 或者每分钟 API 总调
            用数超过 10000 就触发告警。

        为了简化讲解和代码实现，我们假设自定义的告警规则只包含“||、&&、>、<、==”这
        五个运算符，其中，“>、<、==”运算符的优先级高于“||、&&”运算符，“&&”运算
        符优先级高于“||”。在表达式中，任意元素之间需要通过空格来分隔。除此之外，用户可
        以自定义要监控的 key，比如前面的 api_error_per_minute、api_count_per_minute。
         */

        // 使用解释器模式去解析下面的规则，然后判断该规则在填充下面数据的情况下返回什么
        var rule = "key1 > 100 && key2 < 30 || key3 < 100 || key4 = 88";
        rule = "key1 > 100 && ( key2 < 30 || key3 < 100 || key4 = 88 )";
        rule = "( key1 > 200 && ( key1 > 100 || key2 < 30 ) ) || ( key2 < 30 || key3 < 100 || key4 = 88 )";

        // 大致实现逻辑就是根据(进行分层，然后根据空格去分割，然后从左侧开始找到一层或者一个表达式就进行处理
        // 剩余的执行上面的逻辑去处理
        var interpreter = new AlertRuleInterpreter2(rule);
        var stats = new Dictionary<string, long> { { "key1", 100 }, { "key2", 80 }, { "key3", 121 }, { "key4", 88 } };
        var alert = interpreter.Interpret(stats);
        Console.WriteLine($"根据告警规则 当前状态为：{(alert ? "警告" : "无警告")}");
    }

    private void CustomRuleHandler3()
    {
        // 使用解释器模式去解析下面的规则，然后判断该规则在填充下面数据的情况下返回什么
        var rule = "column_name ~ 'patient' and table_name ~ base'";
        // rule = "( column_name ~ 'patient' and table_name ~ base' ) or column_name ~ 'visit'";
        // rule = "( column_name ~ 'patient' and table_name ~ base' ) and column_name ~ 'visit'";

        // 大致实现逻辑就是根据(进行分层，然后根据空格去分割，然后从左侧开始找到一层或者一个表达式就进行处理
        // 剩余的执行上面的逻辑去处理
        var interpreter = new IdentityRuleInterpreter3(rule);
        var result = interpreter.Interpret("patient_base_info", "patient_name");
        Console.WriteLine($"判断当前是否满足状态 当前状态为：{(result ? "满足" : "不满足")}");
    }
}